﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Data.Schema.Tools.DataGenerator;
using System.Reflection;
using System.IO;
using Microsoft.Data.Schema.Extensibility;
using Microsoft.Data.Schema.Sql;

namespace DataGenerators
{
    /// <summary>
    /// Generates randomly Person names and sex.
    /// </summary>
    [DatabaseSchemaProviderCompatibility(typeof(SqlDatabaseSchemaProvider))]
    public class NameGenerator : Generator
    {

        #region private attributes

        static string[] _femaleNames = GetFemaleNames();
        static string[] _maleNames = GetMaleNames();
        static string[] _surnames = GetSurnames();

        Random _random;

        #endregion

        /// <summary>
        /// Initializes a new instance of <see cref="NameGenerator"/>
        /// </summary>
        public NameGenerator()
        {
            _random = new Random(this.Seed);
        }

        #region private methods

        private static string[] GetFemaleNames()
        {
            using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("DataGenerators.DataFiles.femalenames.txt"))
            using (StreamReader reader = new StreamReader(stream))
            {
                string names = reader.ReadToEnd();

                return names.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            }
        }

        private static string[] GetMaleNames()
        {
            using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("DataGenerators.DataFiles.malenames.txt"))
            using (StreamReader reader = new StreamReader(stream))
            {
                string names = reader.ReadToEnd();

                return names.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            }
        }

        private static string[] GetSurnames()
        {
            using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("DataGenerators.DataFiles.surnames.txt"))
            using (StreamReader reader = new StreamReader(stream))
            {
                string surnames = reader.ReadToEnd();

                return surnames.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            }
        }

        #endregion

        #region overrides

        /// <summary>
        /// Generates the next value according to the data generation algorithm.
        /// </summary>
        protected override void OnGenerateNextValues()
        {
            int nameAmount = _random.Next(1, 3);
            int surnameAmount = _random.Next(1, 2);

            IsMale = _random.Next(0, 2) == 0;
            string[] names = IsMale ? _maleNames : _femaleNames;

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < nameAmount; i++)
            {
                sb.AppendFormat(" {0}", names[_random.Next(names.Length - 1)]);
            }
            sb.Remove(0, 1);
            Name = sb.ToString();
            sb.Clear();
            for (int i = 0; i < surnameAmount; i++)
            {
                sb.AppendFormat(" {0}", _surnames[_random.Next(_surnames.Length - 1)]);
            }
            sb.Remove(0, 1);
            Surname = sb.ToString();

            FullName = string.Format("{0} {1}", Name, Surname);
        }

        /// <summary>
        /// Generates the next set of values for a data row.
        /// </summary>
        protected override void OnNextValues()
        {
            OnGenerateNextValues();
        }

        /// <summary>
        /// Initializes the generator.
        /// </summary>
        /// <param name="initInfo">
        /// A Microsoft.Data.Schema.Tools.DataGenerator.GeneratorInit object containing
        /// run-time configuration information, such as the database connection string.
        /// Also contains shared instancing information.
        /// </param>
        protected override void OnInitialize(GeneratorInit initInfo)
        {
            _random = new Random(this.Seed);

            base.OnInitialize(initInfo);
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets the random generated Person Name
        /// </summary>
        [Output(Name = "Nombre", Description = "Devuelve un nombre que puede ser simple o compuesto.")]
        public string Name { get; private set; }

        /// <summary>
        /// Gets the random generated Person Surname
        /// </summary>
        [Output(Name = "Apellido", Description = "Devuelve un apellido que puede ser simple o compuesto.")]
        public string Surname { get; private set; }

        /// <summary>
        /// Gets the random generated Person Full Name
        /// </summary>
        [Output(Name = "Nombre Completo", Description = "Devuelve nombre y apellido.")]
        public string FullName { get; private set; }

        /// <summary>
        /// Get the random generated Person Sex
        /// </summary>
        [Output(Name = "Sexo", Description = "Devuelve true si es Varon.")]
        public bool IsMale { get; private set; }

        #endregion
    }
}
